package gld.algo.park;

import java.awt.Point;
import java.util.HashMap;
import java.util.LinkedList;

import gld.algo.tlc.TLController;
import gld.algo.tlc.TLDecision;
import gld.infra.*;
import gld.xml.XMLCannotSaveException;
import gld.xml.XMLElement;

public abstract class AbstractTLC extends TLController {

	private static String shortXMLName = "BasicTLC";

	// A mapping from all tl junctions to its intersection correspondence
	private HashMap<Junction, Intersection> j2i = null;

	// All intersections
	private LinkedList<Intersection> is = null;

	AbstractTLC(Infrastructure i) {
		super(i);
		// TODO Auto-generated constructor stub
	}

	/**
	 * Our version of deciding tls.
	 * 
	 * @return Mapping from junctions to their signs list. We could return just a
	 *         big list of signs, but that may not have enough flexibility and
	 *         control.
	 * @throws InfraException 
	 */
	public abstract HashMap<Junction, HashMap<Sign, Boolean>> getTLDecisions() throws InfraException;

	/**
	 * Below are the useful methods that shall be provided to sub classes.
	 */

	/**
	 * Return all intersections
	 */
	public LinkedList<Intersection> getIntersections() {
		return is;
	}
	
	/**
	 *  Return the intersection corresponding to a junction
	 */
	public Intersection getIntersection(Junction j) {
		return j2i.get(j);
	}
	
	/**
	 *  Put what to do when infra is changed
	 */
	private void infraChanged() {
		generateMappings();
	}
	
	/**
	 * Generate the mapping from junctions to intersections
	 */
	private void generateMappings() {
		// Create new mappings
		is = new LinkedList<Intersection>();
		j2i = new HashMap<Junction, Intersection>();
		Infrastructure infra = getInfrastructure();
		Junction[] js = infra.getJunctions();
		for (Junction j : js) {
			// Use the number of traffic lights to determine if it's a real
			// intersection.
			// Note, some node is marked as "gld.node.Junction" but has no traffic
			// lights, so cannot use the name node.toString() as judge
			if (j.getNumRealSigns() > 0) {
				Intersection i = new Intersection(j,this);
				is.add(i);
				j2i.put(j, i);
			}
		}
	}

	/**
	 * Below are the methods used from TLController
	 */
	public Infrastructure getInfrastructure() {
		return super.getInfrastructure();
	}

	public int getCurCycle() {
		return super.getCurCycle();
	}

	// Override here to inform the change of infrastructure and we can change the
	// list of intersections, etc
	public void setInfrastructure(Infrastructure i) {
		super.setInfrastructure(i);
		infraChanged();
	}

	/**
	 * Completely useless method.
	 */
	@Override
	public void updateRoaduserMove(Roaduser _ru, Drivelane _prevlane,
			Sign _prevsign, int _prevpos, Drivelane _dlanenow, Sign _signnow,
			int _posnow, Drivelane[] _possiblelanes, Point[] _ranges, Drivelane lane) {
		// TODO Auto-generated method stub

	}

	@Override
	public TLDecision[][] decideTLs() {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * Methods below may be required.
	 */
	public XMLElement saveSelf() throws XMLCannotSaveException {
		XMLElement result = super.saveSelf();
		result.setName(shortXMLName);
		return result;
	}

	public String getXMLName() {
		return "model." + shortXMLName;
	}

}
